/********************************************************************************
 * Project Name		[JavaSE_Fundamentals]
 * File Name     	[GenericsWildcard.java]
 * Creation Date 	[2015-01-01]
 * 
 * Copyright© ge.y.yang@gmail.com All Rights Reserved
 * 
 * Work hard, play harder, think big and keep fit
 ********************************************************************************/
package generics;

import java.util.Date;
import java.util.GregorianCalendar;

/**
 * 泛型通配符
 * 
 * @author 不落的太阳(Sean Yang aka ShortPeace)
 * @version 1.0
 * @since jdk 1.8
 * 
 */
public class GenericsWildcard {

	/**
	 * 交换Pair中的first & second的值
	 * 
	 * @param pair
	 */
	private static <T> void swapHelper(Pair<T> pair) {
		T temp = pair.getFirst();
		pair.setFirst(pair.getSecond());
		pair.setSecond(temp);
	}

	/**
	 * 使用?(无限定通配符)时需要借助上面的方法来完成交换
	 * 
	 * @param pair
	 */
	public static void swap(Pair<?> pair) {
		swapHelper(pair);
	}

	/**
	 * 无限定通配符只能使用getters方法<br>
	 * 
	 * 检查null值
	 * 
	 * @param pair
	 * @return
	 */
	public static boolean hasNull(Pair<?> pair) {
		return pair.getFirst() == null && pair.getSecond() == null;
	}

	/**
	 * 打印员工信息
	 * 
	 * @param pair
	 */
	public static void printBuddies(Pair<? extends Employee> pair) {
		Employee first = pair.getFirst();
		Employee second = pair.getSecond();
		System.out.println("First--->" + first.getName() + "  Second---> " + second.getName());
	}

	/**
	 * 查找经理中获得最高和最低奖金的人
	 * 
	 * @param managers
	 * @param pair
	 */
	public static void minmaxBonus(Manager[] managers, Pair<? super Manager> pair) {
		if (managers == null || managers.length == 0) {
			return;
		}
		Manager managerMin = managers[0];
		Manager managerMax = managers[0];
		for (int i = 0; i < managers.length; i++) {
			if (managerMin.getBonus() > managers[i].getBonus()) {
				managerMin = managers[i];
			}
			if (managerMax.getBonus() < managers[i].getBonus()) {
				managerMax = managers[i];
			}
		}
		pair.setFirst(managerMin);
		pair.setSecond(managerMax);
	}

	/**
	 * 交换
	 * 
	 * @param managers
	 * @param pair
	 */
	public static void swapBonus(Manager[] managers, Pair<? super Manager> pair) {
		minmaxBonus(managers, pair);
		swap(pair);
	}

	public static void main(String[] args) {
		Manager ceo = new Manager("Greek", 800000, 2003, 12, 15);
		Manager cfo = new Manager("America", 100000, 2003, 12, 15);

		Pair<Manager> manager = new Pair<Manager>(ceo, cfo);
		printBuddies(manager);

		ceo.setBonus(100000);
		cfo.setBonus(700000);
		Manager[] managers = new Manager[] { ceo, cfo };

		Pair<Employee> employee = new Pair<Employee>();
		minmaxBonus(managers, employee);
		System.out.println("First " + employee.getFirst().getName() + "  Second " + employee.getSecond().getName());

		swapBonus(managers, employee);
		System.out.println("First " + employee.getFirst().getName() + "  Second " + employee.getSecond().getName());
	}
}

/**
 * 
 * @author 不落的太阳(Sean Yang aka ShortPeace)
 * @version 1.0
 * @since jdk 1.8
 *
 */
class Employee {

	private String name;
	private double salary;
	private Date birthday;

	public Employee(String name, double salary, int year, int month, int day) {
		super();
		this.name = name;
		this.salary = salary;
		birthday = new GregorianCalendar(year, month - 1, day).getTime();
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public double getSalary() {
		return salary;
	}

	public void setSalary(double salary) {
		this.salary = salary;
	}

	public Date getBirthday() {
		return birthday;
	}

	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}
}

/**
 * 
 * @author 不落的太阳(Sean Yang aka ShortPeace)
 * @version 1.0
 * @since jdk 1.8
 *
 */
class Manager extends Employee {

	private double bonus;

	public Manager(String name, double salary, int year, int month, int day) {
		super(name, salary, year, month, day);
		bonus = 0;
	}

	@Override
	public double getSalary() {
		return super.getSalary() + bonus;
	}

	public double getBonus() {
		return bonus;
	}

	public void setBonus(double bonus) {
		this.bonus = bonus;
	}
}